﻿var Promise = require('bluebird');
var mongoose = require('mongoose');
var WOvertimeMdl = require('../module/work_overtime');
//var XLSX = require('xlsx');

'use strict'

var exportCtller = new Object(),
    conf_sheetCol_template = {
    char_start_code: 65,
    char_end_code: 90,
    normal_fee: 20,
    weekend_fee: 40,
    detail_sheet: {
        employee_no: 0,
        employee_name: 1,
        weekend_mark: 2,
        normalday_mark: 3,
        overtime_fee: 4,
        fare: 5,
        daysAndMemo: 6,
        row_cols: 7
    },
    fare_sheet: {},
    fee_sheet: {},
    list_sheet: {},
    translateIdx: function (sheet, col) {
        return this[sheet][col];
    },
    transIdxToColID: function (idx) {
        if (idx > 25) {
            return this.transIdxToColID(parseInt(idx / 26) - 1) + String.fromCharCode(this.char_start_code + (idx % 26));
        } else {
            return String.fromCharCode(this.char_start_code + idx);
        }
    },
    getSheetConfOneRowCols: function (sheet) {
        return this[sheet].row_cols;
    }
    },
    queryPromise = function (condition) {
    return new Promise(function (fulfil, reject) {
        WOvertimeMdl.find(condition, function (err, docs) {
            if (err) { reject(err); }
            else { fulfil(docs); }
        });
    });
    },
    analyzeDataPromise = function (dataRng, docs) {
    return new Promise(function (fulfil, reject) {
        var inprom_err = null,
            wb,
            rst,
            conf = {},
            docObj = {
                dynDaysDeltaIndx:[],
                emp_no_arr: [],
                rows: []
            };
        try {
            /// 根据模板设置，将查询结果集转换成特定格式的js对象.
            /// .[emp_no]是以员工编号作为属性名的属性，记录该员工信息集存放在.rows数列中的位置
            /// .rows属性以array or array形式存放每个员工的信息集合
            /// ..row（.rows内的每个元素）以array形式存放员工信息，具体每个元素存放的信息由模板设置决定。
            /// .emp_no_arr属性以array形式存放员工编号，记录本js对象包含的所有员工的员工编号信息
            ///             在输出时，可以对.emp_no_arr进行排序，以得到有序的员工编号，再[.emp_no]属性获取
            ///             该员工信息集存放在.rows数列中的位置
            ///.dynDaysDeltaIndx属性以array形式存放{dtStr:,deltaIdx:}对象，用来记录日期范围内的某日期对应的excel列的相对位置
            docs.forEach(function (doc, i) {
                if (doc.employee_no in docObj) {
                    var rowIdx = docObj[doc.employee_no];
                    var old_row = docObj.rows[rowIdx];
                    if (doc.WeekDay in [0, 6]) {
                        old_row[conf_sheetCol_template.translateIdx("detail_sheet", "weekend_mark")] += 1;
                        old_row[conf_sheetCol_template.translateIdx("detail_sheet", "overtime_fee")] += conf_sheetCol_template.weekend_fee;
                    } else {
                        old_row[conf_sheetCol_template.translateIdx("detail_sheet", "normalday_mark")] += 1;
                        old_row[conf_sheetCol_template.translateIdx("detail_sheet", "overtime_fee")] += conf_sheetCol_template.normal_fee;
                    }
                    if (doc.fare && doc.fare != "0" && doc.fare != "undefined") {
                        old_row[conf_sheetCol_template.translateIdx("detail_sheet", "fare")] += parseInt(doc.fare);
                    }
                    old_row[conf_sheetCol_template.translateIdx("detail_sheet", "daysAndMemo")].push(doc.overtime_date);
                }
                else {
                    var row = new Array(conf_sheetCol_template.getSheetConfOneRowCols("detail_sheet"));
                    row[conf_sheetCol_template.translateIdx("detail_sheet", "employee_no")] = doc.employee_no;
                    row[conf_sheetCol_template.translateIdx("detail_sheet", "employee_name")] = doc.employee_name;
                    if (doc.WeekDay in [0, 6]) {
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "normalday_mark")] = 0;
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "weekend_mark")] = 1;
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "overtime_fee")] = conf_sheetCol_template.weekend_fee;
                    } else {
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "normalday_mark")] = 1;
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "weekend_mark")] = 0;
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "overtime_fee")] = conf_sheetCol_template.normal_fee;
                    }
                    if (doc.fare && doc.fare != "0" && doc.fare != "undefined") {
                        row[conf_sheetCol_template.translateIdx("detail_sheet", "fare")] = parseInt(doc.fare);
                    }
                    row[conf_sheetCol_template.translateIdx("detail_sheet", "daysAndMemo")] = [doc.overtime_date];
                    docObj.rows.push(row);
                    docObj.emp_no_arr.push(doc.employee_no);
                    docObj[doc.employee_no] = docObj.rows.length - 1;
                }
            });
            conf.name = "加班明细";
            conf.cols = [
                {
                    caption: '员工编号',
                    type: 'string'
                }, {
                    caption: '姓名',
                    type: 'string'
                }, {
                    caption: 'D休息',
                    type: 'string'
                }, {
                    caption: 'D工作',
                    type: 'string'
                }, {
                    caption: '¥汇总',
                    type: 'string'
                }, {
                    caption: '报销车费¥',
                    type: 'string'
                }
            ];
            var dynDayCols = [],
                dFrm = new Date(dataRng[0]),
                dTo = new Date(dataRng[1]),
                dynTitleConf = {
                    start: dFrm.getFullYear() + "/" + (dFrm.getMonth() + 1) + "/" + dFrm.getDate(),
                    end: dTo.getFullYear() + "/" + (dTo.getMonth() + 1) + "/" + dTo.getDate(),
                    colCnt: 0,
                    cols: []
                };
            while (dTo.getTime() - dFrm.getTime() >= 0) {
                docObj.dynDaysDeltaIndx.push({
                    dtStr: dFrm.getFullYear()+"/"+(dFrm.getMonth()+1)+"/"+dFrm.getDate(),
                    deltaIdx: docObj.dynDaysDeltaIndx.length
                });
                dynDayCols.push({
                    caption: dFrm.getDate().toString().length == 1 ? "0" + dFrm.getDate() : dFrm.getDate(),
                    type: 'string'
                });
                dynTitleConf.colCnt++;
                dynTitleConf.cols.push({
                    num: dFrm.getDate().toString().length == 1 ? "0" + dFrm.getDate() : dFrm.getDate(),
                    week: (function (weekday) {
                        switch (weekday) {
                            case 0: return "日";
                            case 1: return "一";
                            case 2: return "二";
                            case 3: return "三";
                            case 4: return "四";
                            case 5: return "五";
                            case 6: return "六";
                        }
                    })(dFrm.getDay())
                });
                dFrm.setDate(dFrm.getDate() + 1);
            }
            dynDayCols.push({
                caption: '备注',
                type: 'string'
            });
            conf.cols = conf.cols.concat(dynDayCols);
            conf.rows = [];
            docObj.emp_no_arr
                .sort(function (a, b) { return parseInt(a) - parseInt(b); })
                .forEach(function (v, i) {
                    var row_idx = docObj[v],
                        row = [];
                    docObj.rows[row_idx].forEach(function (v, i) {
                        if (i < conf_sheetCol_template.getSheetConfOneRowCols("detail_sheet") - 1) {
                            if (v instanceof Array) {
                                row.concat(v);
                            } else {
                                row.push(v);
                            }
                        } else {
                            docObj.dynDaysDeltaIndx.forEach(function (dyn_v, dyn_i) {
                                if (v.indexOf(dyn_v.dtStr) >= 0) {
                                    row.push("1");
                                } else {
                                    row.push("");
                                }
                            });
                        }
                    });
                    row.push("");
                    conf.rows.push(row);                    
                });
            rst = { dnyCols: dynTitleConf, rows: conf.rows };
            // exportExcelDataWithTemplet(rst);
        } catch (e) {
            inprom_err = e;
        }
        if (inprom_err) { reject(inprom_err); }
        else {
            fulfil(rst);
        }
    });
    }

//function exportExcelDataWithTemplet(data) {    
//    var workbook = XLSX.readFile(process.cwd() + "/upload/templet.xlsx");
//    var ws = workbook.Sheets["加班明细"];
//}

/**
 * 根据输入参数，生成查询条件，返回查询promise
 * 参数格式 dateFrom:string,dateTo:string,dpt?:string|array[,dpt?:string|array...]
 */
function GetData() {
    var dtFrom = arguments[0],
        dtTo = arguments[1],
        dpt = arguments[2],
        condition; 
    condition = dpt instanceof Array
        ? { OTDate: { $gte: new Date(dtFrom), $lte: new Date(dtTo) }, department_name: { $in: dpt } }
        : dpt
            ? { OTDate: { $gte: new Date(dtFrom), $lte: new Date(dtTo) }, department_name: dpt }
            : { OTDate: { $gte: new Date(dtFrom), $lte: new Date(dtTo) } };
    return queryPromise(condition);
}

/**
 * 参数格式 dateFrom:string,dateTo:string,dpt?:string|array[,dpt?:string|array...]
 * 返回生成excel对象的promise
 */
function BuildExeclData() {
    var dataRng = [arguments[0], arguments[1]];
    return GetData(arguments[0], arguments[1], arguments[2]).then(function (docs) {
        return analyzeDataPromise(dataRng, docs);
    });
}

/**
 * 参数格式 dateFrom:string,dateTo:string,dpt?:string|array[,dpt?:string|array...],callback;function
 */
exportCtller.exportExcel = function () {
    var dtFrom,
        dtTo,
        dpt,
        callback;
    switch (arguments.length) {
        case 0:
        case 1:            
        case 2:
            throw new Error("at least import dateFrom,dateTo and callback");   
        case 3:
            if (typeof arguments[0] == "string" && typeof arguments[1] == "string" ) {
                dtFrom = arguments[0];
                dtTo = arguments[1];
            } else {
                throw new TypeError("plz imp. dateFrom and dateTo");
            }
            callback = arguments[2];
            if (typeof callback != "function") { throw new TypeError("callback is not a function"); }
            break;         
        default:
            dtFrom = arguments[0];
            dtTo = arguments[1];
            callback = arguments[arguments.length - 1];
            if (typeof callback != "function") { throw new TypeError("callback is not a function"); }
            var sliceArgs = Array.prototype.slice.call(arguments, [3, arguments.length-1]);
            dpt = sliceArgs.reduce(function (prev, next) {
                if (!(prev instanceof Array)) { prev = [prev] }
                if (next instanceof Array) {
                    prev.concat(next);
                } else {
                    prev.push(next);
                }
                return prev;
            });
            break;
    }
    BuildExeclData(dtFrom, dtTo, dpt)
        .then(function (dataObj) { callback(null, dataObj);})
        .catch(function (reason) { callback(reason, null);});
};

module.exports = exportCtller;